var caches = {}

function cmp(a, b) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === b[i]) { continue; } else {
            return b[i] - a[i]
        }
    }
}

function findPartMaxProd(n) {
    var products = f(n);
    var arr = products.map(v => v.reduce((s, x) => s *= x, 1));
    var m = Math.max(...arr);
    var out = products.filter((v, i) => arr[i] === m).sort(cmp);
    out.push(m);
    return out;
}

var arrayHasElement = function(array, element) { // 判断二维数组array中是否存在一维数组element
    for (var el of array) {
        if (el.length === element.length) {
            for (var index in el) {
                if (el[index] !== element[index]) {
                    break;
                }
                if (index == (el.length - 1)) { // 到最后一个元素都没有出现不相等，就说明这两个数组相等。
                    return true;
                }
            }
        }
    }
    return false;
}

function f(n) {
    if (Object.keys(caches).includes(n)) return caches[n]
    if (n <= 3) { caches[n] = n; return n; } else {
        var out = []
        var a = [Math.max(2, n - 2), Math.min(2, n - 2)];
        var b = [Math.max(3, n - 3), Math.min(3, n - 3)];
        if (!arrayHasElement(out, a)) out.push(a)
        if (!arrayHasElement(out, b)) out.push(b)
        var sub2 = f(n - 2)
        var sub3 = f(n - 3)
        if (Array.isArray(sub2)) {
            for (x of sub2) {
                var temp = [].concat(x);
                temp.push(2);
                temp = temp.sort((a, b) => b - a)
                if (!arrayHasElement(out, temp))
                    out.push(temp)
            }
        }
        if (Array.isArray(sub3)) {
            for (x of sub3) {
                var temp = [].concat(x);
                temp.push(3);
                temp = temp.sort((a, b) => b - a)
                if (!arrayHasElement(out, temp))
                    out.push(temp)
            }
        }
        if (!Object.keys(caches).includes(n)) caches[n] = out;
        return out;
    }

}
console.log(f(8))
console.log(findPartMaxProd(5))